/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package hormigas_packettracker.config;

import hormigas_packettracker.beans.Carro;
import hormigas_packettracker.beans.Mapa;
import hormigas_packettracker.beans.Moto;
import hormigas_packettracker.beans.Pedido;
import hormigas_packettracker.beans.Punto;
import hormigas_packettracker.beans.Vehiculo;
import hormigas_packettracker.colonia.Nodo;
import java.util.ArrayList;

/**
 *
 * @author Shadow
 */
public class GestorVehiculos {
    
    private static GestorVehiculos _instancia;
    private ArrayList<Vehiculo> _vehiculos = new ArrayList<>();

    public ArrayList<Vehiculo> getVehiculos() {
        return _vehiculos;
    }
    
    public static GestorVehiculos getInstancia(){
        if (_instancia != null) return _instancia;
        _instancia = new GestorVehiculos();
        return _instancia;
    }
    
    private GestorVehiculos(){
    }
    
    public void crearVehiculos (){
        int i = 0;
        int contMoto = 0;
        int contCarro = 0;
        for (; i < Parameters.getNumCarros()+Parameters.getNumMotos(); i++){
            if (Math.random()<=0.5){
                contCarro++;
                _vehiculos.add(new Carro());
            }else {
                _vehiculos.add(new Moto());
                contMoto++;
            }
            if (contMoto == Parameters.getNumMotos())
                for (; i < Parameters.getNumCarros()+Parameters.getNumMotos(); i++){
                _vehiculos.add(new Carro());
                }
            if (contCarro == Parameters.getNumCarros())
                for (;i < Parameters.getNumCarros()+Parameters.getNumMotos(); i++){
                    _vehiculos.add(new Moto());
                }
        }
        
    }
    
    public Vehiculo getVehiculo(int index){
        return _vehiculos.get(index);
    }
    public void asignarRutas(ArrayList<ArrayList<Nodo>> bestRoutes){
        for(int i=0;i<bestRoutes.size();i++){
            ArrayList<Punto> ruta = new ArrayList<>();
            ArrayList<Nodo> solucion = bestRoutes.get(i);
            for(int j=1;j< solucion.size();j++){
                Punto p1 = solucion.get(j-1).getPunto();
                Punto p2 = solucion.get(j).getPunto();
                ArrayList<Punto> segment = GestorVehiculos.Astar(p1,p2);
                if(j!=1)segment.remove(0);
                ruta.addAll(segment);
            }
            this._vehiculos.get(i).setRuta(ruta);
        }
    }
    
    public void actualizarVehiculosYOrdenes(int tiempo,ArrayList<Pedido> ordenes){
        int size = this._vehiculos.size();
        for(int i=0;i<size;i++){
            this._vehiculos.get(i).avanzar(tiempo,ordenes);
        }
    }
    
    public static float geomDistance(Punto p1, Punto p2){
        int x1 = p1.getX();
        int x2 = p2.getX();
        int y1 = p1.getY();
        int y2 = p2.getY();
        return (float) Math.sqrt((x1-x2)*(x1-x2) +(y1-y2)*(y1-y2));
    }

    private static ArrayList<Punto> getCheapestRoute(ArrayList<ArrayList<Punto>> routes, Punto p) {
        ArrayList<Punto> cheapest = null;
        float minCost = Float.POSITIVE_INFINITY;
        for(int i=0;i<routes.size();i++){
            ArrayList<Punto> current = routes.get(i);
            //añadir el costo de las aristas en caso se necesite aristas de difernte peso
            float cost = geomDistance(current.get(current.size()-1),p);
            if(cost <= minCost){
                minCost = cost;
                cheapest = current;
            }
        }
        routes.remove(cheapest);
        return cheapest;
    }
        
    public static ArrayList<Punto> Astar(Punto p1, Punto p2){
        ArrayList<ArrayList<Punto>> routes = new ArrayList<ArrayList<Punto>>();
        ArrayList<Punto> visitados = new ArrayList<Punto>();
        //inicializar una ruta con el nodo inicial
        ArrayList<Punto> route = new ArrayList<Punto>();
        route.add(p1);
        routes.add(route);
        
        while(visitados.size() != Mapa.size()){
            ArrayList<Punto> cheapest = getCheapestRoute(routes,p2);
            Punto ultimo = cheapest.get(cheapest.size()-1);
            if(ultimo == p2)return cheapest;
            for(int i=0;i < ultimo.getnAdj();i++){
                if(!ultimo.getAdj()[i].estaBloqueado() && !visitados.contains(ultimo.getAdj()[i])){
                    ArrayList<Punto> nuevaRuta = (ArrayList<Punto>)cheapest.clone();
                    nuevaRuta.add(ultimo.getAdj()[i]);
                    routes.add(nuevaRuta);
                }
            }
            visitados.add(ultimo);
        }
        return null;
    }
}
